/***************************************************************************************************
  *Copyright(C),2010-2016,Sumscope
  *FileName	:  JsonWideWriter.h
  *Author	:  scofined.qi
  *Version	:  1.0
  *Date		:  2016/09/12
  *Desc		:  //用于主要说明此程序文件完成的主要功能
  *Relation :  
  *Others	:  //其他内容说明
  *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
  *History	:  //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
***************************************************************************************************/
#pragma once

#include <string.h>
#include <stdlib.h>
#include "../strings/simple_array.h"
#include "../core.h"
#include "../Utility.h"

namespace qb{
	namespace base{
/*
	经过测试,性能是RapidJson生成性能的120%-333%,平均为244%

	Rapid json 生成范例:
	JsonParser doc(kObjectType);
	JsonValue record_array(kArrayType);

	obj.AddMember(JsonParser::StringRefType(""), *(bool*)(bin + offset), allocator);
	obj.AddMember(JsonParser::StringRefType(""), JsonParser::StringRefType((const char*)(bin + offset)), allocator);
	record_array.PushBack(jsrecord, doc.GetAllocator());
	doc.AddMember(JsonParser::StringRefType("records"), record_array, doc.GetAllocator());
	JsonStringBuffer buffer;
	JsonWriter writer(buffer);
	doc.Accept(writer);
	records = G2W(buffer.GetString());
*/
class S_CORE_EXPORT JsonWideWriter{		// 将json转化为字符串
	typedef wchar_t Element;
	typedef JsonWideWriter Writer;
    typedef qb::base::SimpleArray<Element> Buffer;
	static  const Element	COMMA = L',';
	static 	const Element	SEMICOLON = L':';
	static 	const Element	LIST_START = L'[';
	static 	const Element	LIST_END = L']';
	static 	const Element	MAP_START = L'{';
	static 	const Element	MAP_END = L'}';
	static  const Element   QUOTATION = L'"';
	bool					m_finished;
	bool					m_rootmap;
	bool					m_rootlist;
	int						m_count;			// 等级
	Buffer*					m_buffer;
public:
	class JsonWriterMap;
	class JsonWriterList{
		Writer*		m_writer;
		int					m_count;
	public:
		JsonWriterList(Writer* writer):m_writer(writer),m_count(0){}
		~JsonWriterList()
		{
			End();
		}
		void End(){
			if (m_writer)
			{
				if (m_count <= 0)
					m_writer->AddString(&LIST_START, 1);
				m_writer->AddString(&LIST_END, 1);
			}
			m_writer = 0;
		}
		Writer* AddMap(){AddHead();return m_writer; }
		Writer* AddList(){ AddHead();return m_writer; }
		void AddString(const Element* str, int len = 0){ AddHead(); m_writer->AddJsonString(str, len); }
		void AddBool(bool bvalue){AddHead();m_writer->AddBool(bvalue);}
		void AddInt(int ivalue){AddHead();m_writer->AddInt(ivalue);}
		void AddUint(unsigned int uvalue){AddHead();m_writer->AddUint(uvalue);}
		void AddUint64(uint64_t u64){AddHead();m_writer->AddUint64(u64);}
		void AddInt64(int64_t ivalue){AddHead();m_writer->AddInt64(ivalue);}
		void AddDouble(double dvalue){AddHead();m_writer->AddDouble(dvalue);}
		void AddHead(){ m_writer->AddString(m_count <= 0 ? &LIST_START : &COMMA, 1); m_count++; }
	};
	class JsonWriterMap{
		Writer*		m_writer;
		int				m_count;
	public:
		JsonWriterMap(Writer* writer):m_writer(writer),m_count(0){}
		~JsonWriterMap()
		{
			End();
		}
		void End(){
			if(m_writer)
			{
				if (m_count <= 0)
					m_writer->AddString(&MAP_START, 1);
				m_writer->AddString(&MAP_END,1);
			}
			m_writer = 0;
		}
		Writer* AddMap(const Element* name){AddHead();m_writer->AddName(name,0);m_writer->AddString(&SEMICOLON,1);return m_writer;}
		Writer* AddList(const Element* name){AddHead();m_writer->AddName(name,0);m_writer->AddString(&SEMICOLON,1);return m_writer;}
		void AddString(const Element* name,const Element* str,int len=0)
		{
			AddHead();
			m_writer->AddName(name);m_writer->AddString(&SEMICOLON,1);
			m_writer->AddJsonString(str, len);
		}
		void AddBool(const Element* name,bool bvalue)
		{
			AddHead();
			m_writer->AddName(name);m_writer->AddString(&SEMICOLON,1);
			m_writer->AddBool(bvalue);
		}
		void AddInt(const Element* name,int ivalue)			{
			AddHead();
			m_writer->AddName(name);m_writer->AddString(&SEMICOLON,1);
			m_writer->AddInt(ivalue);
		}
		void AddUint(const Element* name,unsigned int uvalue){
			AddHead();
			m_writer->AddName(name);m_writer->AddString(&SEMICOLON,1);
			m_writer->AddUint(uvalue);
		}
		void AddUint64(const Element* name,uint64_t u64){
			AddHead();
			m_writer->AddName(name);m_writer->AddString(&SEMICOLON,1);
			m_writer->AddUint64(u64);
		}
		void AddInt64(const Element* name,int64_t ivalue){
			AddHead();
			m_writer->AddName(name);m_writer->AddString(&SEMICOLON,1);
			m_writer->AddInt64(ivalue);
		}
		void AddDouble(const Element* name,double dvalue){
			AddHead();
			m_writer->AddName(name);m_writer->AddString(&SEMICOLON,1);
			m_writer->AddDouble(dvalue);
		}
		void AddHead(){ m_writer->AddString(m_count <= 0 ? &MAP_START : &COMMA, 1); m_count++; }
	};
public:
	typedef JsonWriterList List;
	typedef JsonWriterMap Map;
	JsonWideWriter(int initCapcity = 0);
	~JsonWideWriter();
	int GetCapcity()const;
	void Start(int capcity);
	const Element* c_str();
	int size();

	Writer* AddRootList(){ m_rootlist = true; m_rootmap = false; return this; }
	Writer* AddRootMap(){ m_rootmap = true; m_rootlist = false; return this; }
	Writer* AddMap(const Element* name)
	{
		if (m_count > 0)AddString(&COMMA, 1);
		AddName(name, 0); AddString(&SEMICOLON, 1);
		m_count++;
		return this;
	}
	Writer* AddList(const Element* name)
	{
		if (m_count > 0)AddString(&COMMA, 1);
		AddName(name, 0); AddString(&SEMICOLON, 1);
		m_count++;
		return this;
	}
protected:
	void AddName(const Element* name,int len=0)
	{
		AddString(&QUOTATION,1);
		AddString(name, len);
		AddString(&QUOTATION,1);
	}
	void AddJsonString(const Element* str, int len = 0);
	void AddString(const Element* str,int len=0);
	void AddBool(bool bvalue){AddString(bvalue?L"true":L"false",bvalue?4:5);}
	void AddInt(int ivalue){ Element buf[64] = { 0 }; 
	#if WIN32
	_itow_s(ivalue, buf, 64, 10); 
	#else
	swprintf(buf,60, L"%d",  ivalue);
	#endif
	AddString(buf); }
	void AddUint(unsigned int uvalue){ Element buf[64] = { 0 }; int len = FMTBUFW(buf,L"%u", uvalue); AddString(buf, len); }
	void AddUint64(uint64_t u64){ Element buf[64] = { 0 };
	#if WIN32
	_ui64tow_s(u64, buf, 64, 10); 
	#else
	swprintf(buf, 64, L"%llu", u64);//TODO: 64?
	#endif
	AddString(buf); }
	void AddInt64(int64_t ivalue){ Element buf[64] = { 0 }; 
	#if WIN32
	_i64tow_s(ivalue, buf, 64, 10);
	#else
	swprintf(buf, 64, L"%lld", ivalue);
	#endif
	 AddString(buf); }
	void AddDouble(double dvalue){ Element buf[64] = { 0 }; int len = FMTBUFW(buf,L"%f", dvalue); AddString(buf, len); }
};
}//namespace base;
}//namespace qb;
